open Ast

let rec afficherOperateur operateur =  
  match operateur with
  Plus -> print_string "+"
  | Moins -> print_string "-"
  | Mult -> print_string "*"
  | Div -> print_string "/"
;;

let rec afficherComparateur comparateur = 
  match comparateur with
  Inf -> print_string "<"
  | Sup -> print_string ">"
  | InfEgal -> print_string "<="
  | SupEgal -> print_string "=>"
  | Egal -> print_string "=="
  | Diff -> print_string "!="
;;

let rec afficherArithmetique a = 
  match a with
  NN (entier) -> print_int(entier)
  | NVariable (nom,entry) -> 
      begin
        print_string(nom^"["^(string_of_int entry.entry)^"]")
      end
  | NUnop (a) -> begin print_string("-") ; afficherArithmetique(a) end
  | NBinOp (a1,op,a2) -> begin afficherArithmetique(a1) ; afficherOperateur(op) ; afficherArithmetique(a2) end
;;

let rec afficherArithmetiqueListe al =
  match al with 
  ArL(nArithmetique) -> List.iter (fun x -> begin afficherArithmetique(x)  ; print_string(" , ") end) nArithmetique
;;

let rec afficherAppel appel =
  match appel with
  NAppel (nom,arguments) -> begin print_string(nom^"(") ; afficherArithmetiqueListe(arguments) ; print_endline(");") end
;;

let rec afficherInstruction instruction =
  match instruction with
  NReturn -> print_endline("return")
  | NReturnValeur valeur -> begin print_string("return ") ; afficherArithmetique(valeur) ; print_endline(";") end
  | NAffectation (variable,valeur) -> begin afficherArithmetique(variable) ; afficherArithmetique(valeur) end
  | NAppelMethode (appel) -> afficherAppel(appel)
  | NAppelFonction (variable,appel) -> begin afficherArithmetique(variable) ; print_string(" := "); afficherAppel(appel) end
;;

let rec afficherBoolean boolean =
  match boolean with
  NTrue ->  print_string("true")
  | NFalse -> print_string("false")
  | NCmp (a1,comparateur,a2) -> begin afficherArithmetique(a1) ; afficherComparateur(comparateur) ; afficherArithmetique(a2) end
  | NotBoolean (boolean) -> begin print_string("!") ; afficherBoolean(boolean) end
  | NOr (booleen1,booleen2) -> begin afficherBoolean(booleen1) ; print_string(" OR "); afficherBoolean(booleen2) end
  | NAnd (booleen1,booleen2) -> begin afficherBoolean(booleen1) ; print_string(" AND "); afficherBoolean(booleen2) end
;;

let rec afficherVariableListe noeud =
  match noeud with 
  | ListeVariable(nArithmetique) ->
  List.iter (fun x -> afficherArithmetique(x)) nArithmetique
;;

let rec afficherDeclaration noeud =
  match noeud with 
  | NDeclaration(nom,variableListe) -> 
  begin
    print_string(nom^" ");
    afficherVariableListe(variableListe);
    print_endline(";")
  end
;;


let rec afficherDeclarationsListe noeud =
  match noeud with
  | DecList(nDeclaration) -> List.iter (fun x -> afficherDeclaration(x)) nDeclaration
;;



let rec afficherStatement noeud =
  match noeud with
  | NStatementInstruction(nInstruction) -> afficherInstruction(nInstruction)
  | NIf(nBoolean,nStatement,nStatement2) -> 
  begin
    print_string("if (");
    afficherBoolean(nBoolean);
    print_endline(") then {");
    afficherStatement(nStatement);
    print_endline("}");
    print_endline("else {");
    afficherStatement(nStatement2);
    print_endline("}");
  end
  | NWhile(nBoolean,nStatement) ->
  begin
    print_string("while (");
    afficherBoolean(nBoolean);
     print_endline(") {");
    afficherStatement(nStatement);
    print_endline("}");            
  end    
  | NBlock(declarationsListe,statementsListe) ->
  begin
    afficherDeclarationsListe(declarationsListe);
    List.iter (fun x -> afficherStatement(x)) statementsListe
  end
;;


let rec afficherExpression noeud =
  match noeud with 
  | Na(nArithmetique) -> afficherArithmetique(nArithmetique)
  | Nb(nBoolean) -> afficherBoolean(nBoolean)
;;

let rec afficherArgument noeud = 
  match noeud with 
  NArgument(nArithmetique,letype) ->
  begin
    afficherArithmetique(nArithmetique);
    print_string(" : "^letype^" ,")
  end
;;

let rec afficherArgumentsdeclarationListe noeud = 
  match noeud with
  Al(nArgument) -> List.iter (fun x -> afficherArgument(x)) nArgument
;;

let rec afficherProcedure noeud =
  match noeud with
  NProcedure(nom,adl,nst) -> 
  begin
    print_string(nom^" (");
    afficherArgumentsdeclarationListe(adl);
    print_endline(" )");
    afficherStatement(nst)
  end
;;

let rec afficherFonction noeud =
  match noeud with 
  NFonction(nom,adl,typeRetour,nst) ->  
  begin
    print_string(nom^" (");
    afficherArgumentsdeclarationListe(adl);
    print_endline(") : "^typeRetour^" {");    
    afficherStatement(nst);
    print_endline("}");
  end
;;  

let rec afficherProgramme noeud =
  match noeud with 
  | NProgrammeProcedure(nProcedure) -> afficherProcedure(nProcedure)
  | NProgrammeFonction(nFonction) -> afficherFonction(nFonction)
;;

let rec afficherNoeudPrincipal noeud = 
  match noeud with
  | Programme(fonctions,main) -> 
  begin
    List.iter (fun x -> afficherProgramme(x)) fonctions ;
    afficherStatement(main)
    end
;;


